package com.tdd.api.server.base.util;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;

/**
 *
 * 实现AES加密、解密
 *
 * @author gyhs-fujh
 * @date 2020年7月15日
 */
public class AESUtil {

    private static final String AES_ALG = "AES";
    private static final String AES_CBC_PCK_ALG = "AES/CBC/PKCS5Padding";
    private static final byte[] AES_IV = initIv(AES_CBC_PCK_ALG);
    private static final String CHARSET_UTF8 = "UTF-8";

    /**
     *
     * AES加密
     * @param content 待加密的部分
     * @param aesKey 密钥
     * @return 加密后的字符串
     * @throws Exception 加密异常
     */
    public static String aesEncrypt(String content, String aesKey)  {
        String str = content;
        try {
            str = aesEncrypt(content, aesKey, CHARSET_UTF8);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return str.replaceAll("\r\n", "");
    }

    private static String aesEncrypt(String content, String aesKey, String charset) throws Exception {
        try {
            return Base64.getEncoder().encodeToString(aesEncrypt(content.getBytes(charset), aesKey));
        } catch (Exception e) {
            throw new RuntimeException("AES加密失败：Aescontent = " + content + "; charset = " + charset, e);
        }
    }

    private static byte[] aesEncrypt(byte[] content, String aesKey) throws Exception {
        try {
            Cipher cipher = Cipher.getInstance(AES_CBC_PCK_ALG);
            IvParameterSpec iv = new IvParameterSpec(AES_IV);
            cipher.init(1, new SecretKeySpec(Base64.getDecoder().decode(aesKey), AES_ALG), iv);
            byte[] encryptBytes = cipher.doFinal(content);
            return encryptBytes;
        } catch (Exception e) {
            throw new RuntimeException("AES加密失败：Aescontent = " + content, e);
        }
    }



    /**
     *
     * AES解密
     * @param content 待解密的内容
     * @param aesKey 密钥
     * @return 解密后的字符串
     * @throws Exception 解密异常
     */
    public static String aesDecrypt(String content, String aesKey) {
        try {
            String str = aesDecrypt(content, aesKey, CHARSET_UTF8);
            return str.replaceAll("\r\n", "");
        } catch (Exception e) {
            return null;
        }
    }

    private static byte[] aesDecrypt(byte[] content, String aesKey) throws Exception {
        try {
            Cipher cipher = Cipher.getInstance(AES_CBC_PCK_ALG);
            IvParameterSpec iv = new IvParameterSpec(AES_IV);
            cipher.init(2, new SecretKeySpec(Base64.getDecoder().decode(aesKey), AES_ALG), iv);

            return cipher.doFinal(content);
        } catch (Exception e) {
            throw new RuntimeException("AES解密失败：Aescontent = " + content, e);
        }
    }

    private static String aesDecrypt(String content, String aesKey, String charset) throws Exception {
        return new String(aesDecrypt(Base64.getDecoder().decode(content), aesKey), charset);
    }

    private static byte[] initIv(String fullAlg) {
        try {
            Cipher cipher = Cipher.getInstance(fullAlg);
            int blockSize = cipher.getBlockSize();
            byte[] iv = new byte[blockSize];
            for (int i = 0; i < blockSize; i++) {
                iv[i] = 0;
            }
            return iv;
        } catch (Exception e) {
            int blockSize = 16;
            byte[] iv = new byte[blockSize];
            for (int i = 0; i < blockSize; i++) {
                iv[i] = 0;
            }
            return iv;
        }
    }

    public static void main(String[] args) throws Exception {
        String aesKey = "OPnzsLqpueEKvOdfBMpoWw==";

        System.out.println(aesKey.length());
        String content = "[{\"transseqno\":\"linantest20200728001\",\"timestamp\":\"2020-07-28 10:30:30\",\"requeststr\":[{\"projectno\":\"linantest01\",\"projectname\":\"linantest01\",\"packageno\":\"linantest01\",\"packagename\":\"linantest01\",\"beneficiary\":\"linan\",\"amount\":\"10000\",\"guarantee\":\"奥克斯集团有限公司\",\"uniformsco\":\"913302127301453080\",\"startdate\":\"20200820\",\"enddate\":\"20200831\",\"corp_name\":\"深圳中联银融资担保有限公司\",\"hcmbbak1\":\"\",\"hcmbbak2\":\"\",\"hcmbbak3\":\"\"}]}]";
        String encryptStr = aesEncrypt(content, aesKey);
        System.out.println("AES加密后的字符串："+content);
        System.out.println("AES加密密钥："+aesKey);
        System.out.println("AES加密后的字符串："+encryptStr+";加密字符串的长度："+encryptStr.length());
        String decryptStr = aesDecrypt(encryptStr, aesKey);
        System.out.println("解密后的字符串："+decryptStr);
        System.out.println("===================");
    }
}